/**
 * Copyright 2020 Huawei Technologies Co., Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef AICPU_AICPU_KERNEL_BUILDER_H_
#define AICPU_AICPU_KERNEL_BUILDER_H_

#include "common/aicpu_ops_kernel_builder/kernel_builder.h"

namespace aicpu {
using KernelBuilderPtr = std::shared_ptr<KernelBuilder>;

class AicpuKernelBuilder : public KernelBuilder {
 public:
  /**
   * Singleton access method, Thread safe
   * @return return unique instance in global scope
   */
  static KernelBuilderPtr Instance();

  /**
   * Destructor
   */
  virtual ~AicpuKernelBuilder() = default;

  /**
   * Calc the running size of Operator,then GE will alloc the memsize from
   * runtime The size is consist of the part as follow: 1.kernel so
   * name; 2.kernel func name; 3.Kernel param.
   * @param node Node information, return task_memsize in node's attr
   * @return status whether this operation successful
   */
  ge::Status CalcOpRunningParam(const ge::Node &node) const override;

  /**
   * Copy the data from host to device, then address is alloced by GE, then
   * invoked the runtime's interface to generate the task
   * @param node Node information
   * @param run_context
   * @return status whether operation successful
   */
  ge::Status GenerateTask(const ge::Node &node,
                          const ge::RunContext &run_context,
                          std::vector<domi::TaskDef> &tasks) override;

 private:
  /**
   * Task's callback, in the Gen model, client register the callback in the
   * runtime, after launch kernel, runtime will feedback the taskinfo to client
   * @param model runtime's model
   * @param taskInfo runtime's task info
   * @return whether handle successfully
   */

  /**
   * Build the struct AicpuKernelFixedParam, then launch the task
   * @param op_desc_ptr Op description pointer
   * @param run_context GE's run_context
   * @param kernel_def Kernel task info
   * @return status whether operation successful
   */
  ge::Status BuildAndLaunchKernel(const ge::OpDescPtr &op_desc_ptr,
                                  const ge::RunContext &run_context,
                                  domi::KernelDef *&kernel_def) const;

  /**
   * Make aicpu kernel task extend info
   * @param op_desc_ptr Ge op description pointer
   * @param task_ext_info task extend info
   * @return whether handle success
   */
  ge::Status MakeAicpuKernelExtInfo(const ge::OpDescPtr &op_desc_ptr,
                                    std::vector<char> &task_ext_info) const;

  /**
   * Constructor
   */
  AicpuKernelBuilder() = default;

  // Copy prohibited
  AicpuKernelBuilder(const AicpuKernelBuilder &aicpu_kernel_builder) = delete;

  // Move prohibited
  AicpuKernelBuilder(const AicpuKernelBuilder &&aicpu_kernel_builder) = delete;

  // Copy prohibited
  AicpuKernelBuilder &operator=(
      const AicpuKernelBuilder &aicpu_kernel_builder) = delete;

  // Move prohibited
  AicpuKernelBuilder &operator=(AicpuKernelBuilder &&aicpu_kernel_builder) =
      delete;

 private:
  // singleton instance
  static KernelBuilderPtr instance_;
};
}  // namespace aicpu
#endif  // AICPU_AICPU_KERNEL_BUILDER_H_
